<?php
/**
 * 短信发送管理类 无需继承任何类
 * Created by PhpStorm.
 * User: Cocolait
 * Date: 2016/12/12
 * Time: 15:30
 * 博  客：http://www.mgchen.com
 */
namespace Cocolait;
use think\Db;
final class CpSMS{

    /**
     * 短信发送 [阿里大鱼] 多场景发送
     * @param string $mobile            收信人手机号
     * @param string $display_name      后台生成的短信模板名称
     * @param string $option_name       SMS配置名称,系统默认是短信配置,如修改了源码,自行更正
     * @param string $debug             debug 调式错误可用 为True时 表示打开 默认是关闭的
     * @return array ['error'=>'错误码','msg'=>'提示信息'] error : 1 有错误 2：debug错误提示 0:表示无错误,发送成功
     */
    protected static function send($mobile, $display_name , $option_name = '短信配置', $debug = false) {
        //载入阿里大鱼短信发送入口文件
        require_once EXTEND_PATH. 'AlidayuSMS/TopSdk.php';
        //定义发送的默认时区
        date_default_timezone_set('Asia/Shanghai');

        //检测配置是否已配置
        $find_data = Db::name('options')->where(['option_name' => $option_name])->value('option_value');
        if (!$find_data) return ['error'=>1,'msg'=>'配置参数错误,请检查是否有配置'];
        $result = json_decode($find_data,true);
        //实例化阿里大鱼主调用类
        $c = new \TopClient;
        $c->appkey = $result['appkey'];
        $c->format = $result['format'];
        $c->secretKey = $result['secretKey'];

        //实例化短信请求类
        $req = new \AlibabaAliqinFcSmsNumSendRequest;
        //设置发送的类型
        $req->setSmsType("normal");
        //匹配模板
        $display = Db::name('send_note')->where(['display_name'=>$display_name])->find();
        if (!$display) return ['error'=>1,'msg'=>'短信模板不存在,请检查是否有配置'];
        if ($display['is_status']) return ['error'=>1,'msg'=>'该短信模板已关闭,无法使用'];
        //设置短信签名
        $req->setSmsFreeSignName($display['free_sign_name']);
        //匹配默认变量
        $product = '';
        //设置短信内容和发送码
        $SMSCode = (string) CpMsubstr::rand_string(6,1);
        $json = [
            'code' => $SMSCode,
            'product' => (string) $product
        ];
        //处理 登录密码更新提醒 参数替换
        if ($display == 7) {
            unset($json['code']);
            $json['time'] = date('Y-m-d H:i:s',time());
        }
        //设置短信变量，必须和阿里云申请模板中的变量名一致
        $req->setSmsParam(json_encode($json));
        //短信接收号码
        $req->setRecNum($mobile);
        //短信模板ID
        $req->setSmsTemplateCode($display['template_code']);
        $resp = get_object_vars($c->execute($req));
        if ($resp['result']) {
            //短信发送成功 写入数据库用于短信验证
            Db::name('check_phone')->insert([
                'phone' => (string) $mobile,
                'sub_time' => time(),
                'code' => (string) $json['code'],
                'check_item' => $mobile . "_" . $json['code'] . "_" . $display['scene'],
                'note_display_name'     => $display['display_name']
            ]);
            return ['error'=>0,'msg'=>'发送成功'];
        } else {
            if ($debug) {
                return ['error'=>2,'msg'=> $resp];
            }
            return ['error'=>1,'msg'=>'发送失败'];
        }
    }

    /**
     * @param $phone 验证手机号码
     * @param $code  短信验证码
     * @param $scene 验证场景标识
     * @return array|bool
     * @throws \think\Exception
     */
    public static function check_code($phone,$code,$scene) {
        if (empty($phone) || empty($code)) return false;
        $check_item = $phone . "_" . $code . "_" . $scene;
        if ($old = Db::name('check_phone')->where(['check_item' => $check_item,'is_del'=>0])->find()) {
            //验证通过
            //计算时间 分钟
            $time = round((time() - $old['sub_time']) / 60);
            if ($time > 30) {
                return ['error'=>1,'msg'=>'短信验证码已过期'];
            }
            //修改状态
            Db::name('check_phone')->where(['id' => $old['id']])->update([
                'check_time' => time(),
                'is_check' => 1
            ]);
            return ['error'=>0,'msg'=>'验证成功'];
        } else {
            return ['error'=>0,'msg'=>'验证失败'];
        }
    }


    /**
     * 第二层验证 验证通过过可删除也可保留 [这个是拓展,有些需求会用到]
     * @param $phone 验证手机号码
     * @param $code  短信验证码
     * @param $scene  验证场景标识
     * @return bool
     */
    public static function check_two_code($phone,$code,$scene) {
        if (empty($phone) || empty($code)) return false;
        $check_item = $phone . "_" . $code . "_" . $scene;
        if ($id = Db::name('check_phone')->where(['check_item' => $check_item,'is_check'=>1])->value('id')) {
            Db::name('check_phone')->where(['id'=>$id])->setField('is_del',1);
            return true;
        } else {
            return false;
        }
    }
}